package li.wei.sentinel.sentinel.esb;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import li.wei.sentinel.SentinelRuleConfig;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;

/**
 * Created by liwei on 2018/8/29.
 * 模拟esb的调用，其实就是一个方法啦
 *
 * 问题：
 * 1、这次动态修改的配置，没有对下个请求生效    已解决
 * 2、异常比例的阈值越大，跟实际就越不符合，  针对异常比例在0.25以下较准确。。在0.25以上的我需要做个测试统计
 */
@RestController
public class EsbInvoker {

    private SentinelRuleConfig sentinelRuleConfig = new SentinelRuleConfig();

    //调用方法
    @RequestMapping("invoke/{srvName}")
    public String invoke(@PathVariable("srvName") String srvName, HttpServletRequest request){
        String response = "";
        String host = request.getRemoteHost();
        String flowResource = host+srvName;
        String degradeResource = srvName;
        String origin = host;

        Entry flowEntry = null;
        Entry degradeEntry = null;

        try {
            if(sentinelRuleConfig.isFlowRuleOpen()){
                addFlowResourceWhenFirstRequest(flowResource,origin);
                ContextUtil.enter(flowResource, origin);
                flowEntry = SphU.entry(flowResource);
            }
            if(sentinelRuleConfig.isDegradeRuleOpen()){
                addDegradeResourceWhenFirstRequest(degradeResource);
                degradeEntry = SphU.entry(degradeResource);
            }

            //根据方法名去调用具体的hsf/c/http/soap等服务。
            String result = doInvoke(srvName);
            response = result;
        }catch (BlockException e1) {
            e1.printStackTrace();   //直接将异常打出来
            response = flowResource+e1.toString();
        } catch (Throwable t) {
            //统计异常比例
            if (!BlockException.isBlockException(t)) {
                Tracer.trace(t);
                response =System.currentTimeMillis()+":"+ flowResource + "-->"+t.toString();
            }
        } finally {
            if (degradeEntry != null) {
                degradeEntry.exit();
            }
            if (flowEntry != null) {
                flowEntry.exit();
            }
            ContextUtil.exit();
        }
        return response;
    }

    private void addFlowResourceWhenFirstRequest(String flowResource,String origin) {
        if(!sentinelRuleConfig.containsFlowResource(flowResource)){
            sentinelRuleConfig.configFlowRule(flowResource,origin);
        }
    }

    private void addDegradeResourceWhenFirstRequest(String degradeResource) {
        if(!sentinelRuleConfig.containsDegradeResources(degradeResource)){
            sentinelRuleConfig.configDegradeRule(degradeResource);
        }
    }

    int i = 0;
    private String doInvoke(String srvName) {
        if(srvName.matches(".*\\d+.*")){
            String s = srvName.substring(srvName.length() - 1, srvName.length());
            int r = Integer.parseInt(s);
            if(i%r == 0){
                i++;
                throw new IllegalArgumentException("number containes in srvName");
            }
            i++;
        }
        return srvName+"执行成功";
    }




}
